﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Net;
using YourWorldServer;

namespace PolicyServer
{
    class PolicyServer
    {
        private byte[] clientaccesspolicy;
        private TcpListener tcpListener;
        private TcpClient tcpClient;
        private byte[] receivedBytes;
        private static string policyRequestString = "<policy-file-request/>";

        private static string ClientAccessPolicy = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
        "<access-policy>" +
          "<cross-domain-access>" +
            "<policy>" +
             " <allow-from>" +
                "<domain uri=\"*\" />" +
            "  </allow-from>" +
             " <grant-to>" +
              "  <socket-resource port=\"4531\" protocol=\"tcp\" />" +
             " </grant-to>" +
           " </policy>" +
         " </cross-domain-access>" +
        "</access-policy>";

        public void StartPolicyServer()
        {
            try
            {
                clientaccesspolicy = UTF8Encoding.ASCII.GetBytes( ClientAccessPolicy );

                tcpListener = new TcpListener( IPAddress.Any, 943 );
                tcpListener.Start();
                tcpListener.BeginAcceptTcpClient( new AsyncCallback( OnBeginAcceptTcpClient ), null );
            }
            catch ( Exception e )
            {
                Console.WriteLine( "Error creating the policy server: " + e.Message );
                this.StopPolicyServer();
            }
        }

        private void OnBeginAcceptTcpClient( IAsyncResult ar )
        {
            try
            {
                receivedBytes = new byte[policyRequestString.Length];

                tcpClient = tcpListener.EndAcceptTcpClient( ar );
                tcpClient.Client.BeginReceive( receivedBytes, 0, policyRequestString.Length, SocketFlags.None, new AsyncCallback( OnReceive ), null );
            }
            catch ( Exception e )
            {
                Console.WriteLine( "Error creating the policy server: " + e.Message );
                this.StopPolicyServer();
            }
        }

        private void OnReceive( IAsyncResult ar )
        {
            try
            {
                int receivedLength = tcpClient.Client.EndReceive( ar );
                string policyRequest = Encoding.UTF8.GetString( receivedBytes, 0, receivedLength );

                if ( policyRequest.Equals( policyRequestString ) )
                {
                    tcpClient.Client.BeginSend(
                        clientaccesspolicy,
                        0,
                        clientaccesspolicy.Length,
                        SocketFlags.None,
                        new AsyncCallback( OnSend ),
                        null );
                }

                tcpListener.BeginAcceptTcpClient( new AsyncCallback( OnBeginAcceptTcpClient ), null );
            }
            catch ( Exception e )
            {
                Console.WriteLine( "Error initializing the policy server: " + e.Message );
                this.StopPolicyServer();
            }
        }

        private void OnSend( IAsyncResult ar )
        {
            try
            {
                tcpClient.Client.Close();
            }
            catch ( Exception e )
            {
                Console.WriteLine( "Error initializing the policy server: " + e.Message );
                this.StopPolicyServer();
            }
        }

        public void StopPolicyServer()
        {
            try
            {
                if ( tcpListener != null )
                    tcpListener.Stop();
            }
            catch ( Exception e )
            {
                Console.WriteLine( "Error closing the policy server: " + e.Message );                                
            }

            try
            {
                if ( tcpClient != null )
                    tcpClient.Close();
            }
            catch ( Exception e )
            {
                Console.WriteLine( "Error closing the policy server: " + e.Message ); 
            }
        }
    }
}
